perm filename PMAIN.2[EAL,HE] blob sn#676507 filedate 1982-09-27 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00005 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	{$NOMAIN	Parser: main part }
C00007 00003	(* Statement parser: stmntParse *)
C00013 00004	(* Called by EDIT: eStmntParse *)
C00015 00005	(* program parser *)
C00018 ENDMK
C⊗;
{$NOMAIN	Parser: main part }

%include palhdr.pas;

{ Externally defined routines from elsewhere: }

	(* From ALLOC *)
function newStatement: statementp;				external;

	(* From PAUX1 *)
function upperCase(c: ascii): ascii;				external;
procedure appendEnd(s,so: statementp);				external;

	(* From PAUX2 *)
procedure errprnt;						external;
procedure ppFlush;						external;

	(* From PTOKEN *)
procedure getToken;						external;

	(* From PBLOCK *)
function blockParse(st: statementp): boolean;			external;
function coblockParse(st: statementp): boolean;			external;
function endParse(st: statementp): boolean;			external;

	(* From POV1 *)
function assignParse(st: statementp): boolean;			external;
function ifParse(st: statementp): boolean;			external;
function forParse(st: statementp): boolean;			external;
function whileParse(st: statementp): boolean;			external;
function untilParse(st: statementp): boolean;			external;
function caseParse(st: statementp): boolean;			external;

	(* From POV2 *)
function returnParse(st: statementp): boolean;			external;
function affixParse(st: statementp): boolean;			external;
function unfixParse(st: statementp): boolean;			external;
function signlParse(st: statementp): boolean;			external;
function pauseParse(st: statementp): boolean;			external;
function printParse(st: statementp): boolean;			external;
function dimensionParse(st: statementp): boolean;		external;

	(* From POV3 *)
function enableParse(st: statementp): boolean;			external;
function stopParse(st: statementp): boolean;			external;
function retryParse(st: statementp): boolean;			external;
function wristParse(st: statementp): boolean;			external;
function requireParse(st: statementp): boolean;			external;
procedure file1Open (fn: c20str);				external;
function defineParse(st: statementp): boolean;			external;

	(* From PCLAUS *)
function clauseParse(absSeen: boolean): nodep;			external;

	(* From PCMON *)
function cmonParse(st: statementp; deferred: boolean): boolean;	external;

	(* From PARMVE *)
function moveParse(st: statementp): boolean;			external;

	(* From PP *)
procedure ppLine; 						external;
procedure ppOutNow; 						external;
procedure ppChar(ch: ascii); 					external;
procedure pp5(ch: c5str; length: integer); 			external;
procedure pp10(ch: cstring; length: integer); 			external;
procedure pp10L(ch: cstring; length: integer);			external;
procedure pp20(ch: c20str; length: integer); 			external;
procedure pp20L(ch: c20str; length: integer); 			external;
procedure ppInt(i: integer); 					external;
procedure ppStrng(length: integer; s: strngp); 			external;

(* Statement parser: stmntParse *)

function stmntParse: statementp; external;
function stmntParse;
 var badstmnt: boolean; st,sp,se: statementp;
 begin
 getToken;			(* get first token in statement *)
 with curToken do
  while (ttype = delimtype) and (ch = ';') do getToken;
 flushcomments := true;		(* don't allow comments anywhere else *)
 endOk := endOk - 1;
 coendOk := coendOk - 1;
 badstmnt := false;		(* assume everything will be fine *)
 st := newStatement;
 with curToken do		(* see what we've got *)
  begin
  if ttype = labeldeftype then
    begin			(* a label *)
    lab↑.s := st;		(* define it *)
    st↑.stlab := lab;		(* copy pointer to label *)
    getToken;			(* move on to start of statement *)
    end
   else st↑.stlab := nil;

  semiseen := false;
  if (ttype = reswdtype) and (rtype = stmnttype) then
    begin
    st↑.stype := stmnt;
    case stmnt of
blocktype:	badstmnt := blockParse(st);
coblocktype:	badstmnt := coblockParse(st);
endtype,
coendtype:	badstmnt := endParse(st);
iftype:		badstmnt := ifParse(st);
fortype:	badstmnt := forParse(st);
whiletype:	badstmnt := whileParse(st);
casetype:	badstmnt := caseParse(st);
returntype:	badstmnt := returnParse(st);
pausetype:	badstmnt := pauseParse(st);
printtype,
prompttype,
aborttype:	badstmnt := printParse(st);

affixtype:	badstmnt := affixParse(st);
unfixtype:	badstmnt := unfixParse(st);
signaltype,
waittype:	badstmnt := signlParse(st);

movetype,
opentype,
closetype,
centertype,
operatetype:	badstmnt := moveParse(st);

stoptype:	badstmnt := stopParse(st);
retrytype:	badstmnt := retryParse(st);
cmtype:		badstmnt := cmonParse(st,false);
enabletype,
disabletype:	badstmnt := enableParse(st);

wristtype:	badstmnt := wristParse(st);

setbasetype:	badstmnt := false;

requiretype:	badstmnt := requireParse(st);

definetype:	badstmnt := defineParse(st);
dimdeftype:	badstmnt := dimensionParse(st);

assigntype:	begin				(* shouldn't get here *)
		badstmnt := true;	(* could try to recover, but... *)
		pp20L('Need a variable to a',20); pp10('ssign to. ',9); ppFlush;
		errprnt;
		end;
otherwise 	{do nothing};
     end
    end
   else if (ttype = reswdtype) and (rtype = filtype) and
	   ((filler = dotype) or (filler = defertype)) then
    begin
    if filler = dotype then badstmnt := untilParse(st)
     else
      begin
      st↑.stype := cmtype;
      getToken;
      if (ttype = reswdtype) and (rtype = stmnttype) and (stmnt = cmtype) then
	badstmnt := cmonParse(st,true)
       else
	begin
	badstmnt := true;
	pp20L('Expecting an ON here',20); ppChar('.'); ppFlush;
	errprnt;
	end
      end
    end
   else if (ttype = identtype) or
	   ((ttype = reswdtype) and (rtype = optype)) then
	 badstmnt := assignParse(st)
   else if ttype = comnttype then
    begin			(* comment *)
    st↑.stype := commenttype;
    st↑.str := str;		(* copy string pointer *)
    st↑.len := len;
    st↑.cbody := nil;
    end
   else 
    begin			(* no good - complain *)
    badstmnt := true;
    pp20L('Can''t start a statem',20); pp20('ent this way.       ',13);
    errprnt;
    end;

  if badstmnt then
    begin
    st↑.stype := emptytype;	(* return empty statement *)
    end;

  while badstmnt do		(* leave things in a "clean" state *)
   begin
   if (ttype = reswdtype) and
	(rtype = stmnttype) and (stmnt <> assigntype) then 
   (* should also maybe stop when we hit a "DO", but then again maybe not *)
     begin badstmnt := false; backup := true end
    else if (ttype = delimtype) and (ch = ';') then badstmnt := false
    else getToken;		(* if still bad try next token *)
   end;
  end;
 stmntParse := st;
 end;

(* Called by EDIT: eStmntParse *)

function eStmntParse(var cblk,newDecs: statementp; cproc: varidefp): statementp; external;
function eStmntParse;
 var s: statementp; i: integer;
 begin					(* parse last line typed at editor *)
 for i := 1 to maxChar+1 do line[i] := listing[i];
	(* ↑ ↑ ↑    This used to be a call to eCopyLine *)
 curChar := 1;
 eofError := false;
 backup := false;
 curToken.next := nil;
 newDeclarations := nil;
 curBlock := cblk;
 outerBlock := cblk;
 while outerBlock↑.bparent <> nil do outerBlock := outerBlock↑.bparent;
 curVariable := nil;
 curProc := cproc;
 curMotion := nil;			(* assume not *)
 curCmon := nil;			(*   ditto    *)
 curErrhandler := nil;			(*   ditto    *)
 endOk := 0;
 coendOk := 0;
 flushcomments := true;
 inCoblock := false;			(* assume we're not *)
 filedepth := 0;
 eStmntParse := stmntParse;		(* go do it *)
 if newDeclarations <> nil then
   begin				(* set things up the way edit expects *)
   s := newDeclarations↑.last;
   while s↑.stype <> blocktype do s := s↑.last;
   s↑.bcode := newDeclarations↑.next;	(* splice new decs out *)
   end;					(* edit will put them back in *)
 newDecs := newDeclarations
 end;

(* program parser *)

function parse(fname: c20str; ppn: integer): statementp; external;
function parse;
 var s,st: statementp; i: integer;
 begin
 macrodepth := 0;
 expandmacros := true;
 curchar := 1;
 maxchar := -1;
 curline := 0;
 curpage := 1;
 eofError := false;
 backup := false;
 curToken.next := nil;
 curBlock := nil;
 outerBlock := nil;
 curVariable := nil;
 curProc := nil;
 curMotion := nil;
 curCmon := nil;
 curErrhandler := nil;
 flushcomments := true;
 dimCheck := false;		(* turn off dimension checking for now *)
 if fname[1] = '*' then filedepth := 0	(* use tty *)
  else
   begin
   filedepth := 1;
   file1Open(fname);		(* Open the file on file1 *)
   getToken;			(* this should flush the E directory *)
   backup := true;
   end;
 errcount := 0;
 s := newStatement;
 with s↑ do
  begin
  stype := progtype;
  pcode := stmntParse;
  if pcode↑.stype <> blocktype then
    begin		(* make sure program enclosed in begin-end block *)
    st := newStatement;
    with st↑ do
     begin
     stype := blocktype;
     bparent := nil;
     blkid := nil;
     variables := nil;
     bcode := s↑.pcode;
     appendEnd(st,bcode);
     end;
    pcode := st;
    end;
  errors := errcount;
  appendEnd(s,pcode);
  end;
 if errcount = 0 then pp20L('No errors detected  ',18)
  else begin pp20L('Errors detected:    ',16); ppInt(errcount) end;
 ppLine;
 parse := s;
 end;